home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Libraries / Framework / Sources / UScroller.cp < prev    next >
Encoding:
Text File  |  1996-04-03  |  25.9 KB  |  909 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------------
  2. // UScroller.cp 
  3. // Copyright © 1987-96 by Apple Computer, Inc. All rights reserved.
  4. //----------------------------------------------------------------------------------------
  5.  
  6. #ifndef __USCROLLER__
  7. #include "UScroller.h"
  8. #endif
  9.  
  10. // MacApp
  11.  
  12. #ifndef __UCOMMAND__
  13. #include "UCommand.h"
  14. #endif
  15.  
  16. #ifndef __UCONTROL__
  17. #include "UControl.h"
  18. #endif
  19.  
  20. #ifndef __UCOREGLOBALS__
  21. #include "UCoreGlobals.h"
  22. #endif
  23.  
  24. #ifndef __UCOREUTILITIES__
  25. #include "UCoreUtilities.h"
  26. #endif
  27.  
  28. #ifndef __UDEBUG__
  29. #include "UDebug.h"
  30. #endif
  31.  
  32. #ifndef __UDOCUMENT__
  33. #include "UDocument.h"
  34. #endif
  35.  
  36. #if qDrag
  37. #ifndef __UDRAGDROP__
  38. #include "UDragDrop.h"
  39. #endif
  40. #endif
  41.  
  42. #ifndef __UEVENT__
  43. #include "UEvent.h"
  44. #endif
  45.  
  46. #ifndef __UFAILURE__
  47. #include "UFailure.h"
  48. #endif
  49.  
  50. #ifndef __UGEOMETRY__
  51. #include "UGeometry.h"
  52. #endif
  53.  
  54. #ifndef __ULIST__
  55. #include "UList.h"
  56. #endif
  57.  
  58. #ifndef __UMACAPPGLOBALS__
  59. #include "UMacAppGlobals.h"
  60. #endif
  61.  
  62. #ifndef __UMACAPPUTILITIES__
  63. #include "UMacAppUtilities.h"
  64. #endif
  65.  
  66. #ifndef __UPATCH__
  67. #include "UPatch.h"
  68. #endif
  69.  
  70. #ifndef __USTREAM__
  71. #include "UStream.h"
  72. #endif
  73.  
  74. #ifndef __UVIEWSERVER__
  75. #include "UViewServer.h"
  76. #endif
  77.  
  78. #ifndef __UWINDOW__
  79. #include "UWindow.h"
  80. #endif
  81.  
  82. // Toolbox
  83.  
  84. #ifndef __CONTROLS__
  85. #include <Controls.h>
  86. #endif
  87.  
  88. #ifndef __DIALOGS__
  89. #include <Dialogs.h>
  90. #endif
  91.  
  92. // ANSI
  93.  
  94. #ifndef __STDIO__
  95. #include <stdio.h>
  96. #endif
  97.  
  98. #ifndef __STDLIB__
  99. #include <stdlib.h>
  100. #endif
  101.  
  102.  
  103. //========================================================================================
  104. // GLOBAL Procedures
  105. //========================================================================================
  106. static VCoordinate ProportionalScroll(VCoordinate diff,
  107.                                       VCoordinate scrollUnit,
  108.                                       VCoordinate maxTranslationchange);
  109.  
  110. #undef Inherited
  111.  
  112. //----------------------------------------------------------------------------------------
  113. // ProportionalScroll: 
  114. //----------------------------------------------------------------------------------------
  115. #pragma segment MADoCommand
  116.  
  117. VCoordinate ProportionalScroll(VCoordinate diff,
  118.                                VCoordinate scrollUnit,
  119.                                VCoordinate maxTranslationchange)
  120. {
  121.     VCoordinate returnVal = 0;
  122.     if (scrollUnit)
  123.         returnVal = MinMax(scrollUnit, (((diff + (scrollUnit / 2)) / scrollUnit) * scrollUnit), maxTranslationchange);
  124.  
  125.     return returnVal;
  126. } // ProportionalScroll 
  127.  
  128.  
  129. //========================================================================================
  130. // CLASS TScroller
  131. //========================================================================================
  132. #undef Inherited
  133. #define Inherited TView
  134.  
  135. #pragma segment MAOpen
  136. MA_DEFINE_CLASS_M1(TScroller, Inherited);
  137.  
  138. //----------------------------------------------------------------------------------------
  139. // TScroller constructor
  140. //----------------------------------------------------------------------------------------
  141. #pragma segment MAOpen
  142.  
  143. TScroller::TScroller()
  144. {
  145.     fSBarOffsets = gZeroVRect;
  146.     fScrollLimit = gZeroVPt;
  147.     fMaxTranslation = gZeroVPt;
  148.     fScrollUnit = VPoint(kStdScrollUnit, kStdScrollUnit);
  149.     fScrollBars[hSel] = NULL;
  150.     fScrollBars[vSel] = NULL;
  151.     fScrollBarIdentifiers[hSel] = kNoIdentifier;
  152.     fScrollBarIdentifiers[vSel] = kNoIdentifier;
  153.     fConstrain[hSel] = FALSE;
  154.     fConstrain[vSel] = FALSE;
  155.     fRespondsToFunctionKeys = TRUE;
  156. } // TScroller::TScroller
  157.  
  158. //----------------------------------------------------------------------------------------
  159. // TScroller::IScroller: 
  160. //----------------------------------------------------------------------------------------
  161. #pragma segment MAOpen
  162.  
  163. void TScroller::IScroller(TView* itsSuperView,
  164.                                  const VPoint& itsLocation,
  165.                                  const VPoint& itsSize,
  166.                                  SizeDeterminer itsHSizeDet,
  167.                                  SizeDeterminer itsVSizeDet,
  168.                                  const VPoint& itsMax,
  169.                                  Boolean wantHorzSBar,
  170.                                  Boolean wantVertSBar)
  171.  
  172. {
  173.     TDocument * itsSuperViewsDocument = NULL;
  174.  
  175.     if (itsSuperView)
  176.         itsSuperViewsDocument = itsSuperView->fDocument;
  177.  
  178.     this->IView(itsSuperViewsDocument, itsSuperView, itsLocation, itsSize, itsHSizeDet, itsVSizeDet);
  179.  
  180.     FailInfo fi;
  181.     Try(fi)
  182.     {
  183.         this->SetScrollParameters(VPoint(kStdScrollUnit, kStdScrollUnit), FALSE, FALSE);
  184.     
  185.         this->SetScrollLimits(itsMax, kDontRedraw);
  186.     
  187.         if (wantHorzSBar)
  188.             this->CreateScrollBar(hSel);
  189.         if (wantVertSBar)
  190.             this->CreateScrollBar(vSel);
  191.  
  192.         fi.Success();
  193.     }
  194.     else
  195.     {
  196.         this->Free();
  197.         fi.ReSignal();
  198.     }
  199.  
  200.     if (wantHorzSBar || wantVertSBar)
  201.         this->AdjustScrollBars(kDontInvalidate);
  202. } // TScroller::IScroller 
  203.  
  204. //----------------------------------------------------------------------------------------
  205. // TScroller::Clone: 
  206. //----------------------------------------------------------------------------------------
  207. #pragma segment MAScrollerNonRes
  208.  
  209. TObject* TScroller::Clone()            // override 
  210. {
  211.     MAVolatileInit(TScroller*, aClonedScroller, (TScroller *)(Inherited::Clone()));
  212.  
  213.     aClonedScroller->fScrollBars[vSel] = NULL;    // so failure handler works
  214.     aClonedScroller->fScrollBars[hSel] = NULL;
  215.  
  216.     for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  217.     {
  218.         if (fScrollBars[vhs])
  219.         {
  220.             FailInfo fi;
  221.             Try(fi)
  222.             {
  223.                 aClonedScroller->fScrollBars[vhs] = (TScrollerScrollBar*)(fScrollBars[vhs]->Clone());
  224.                 aClonedScroller->fScrollBars[vhs]->AttachScroller(aClonedScroller);
  225.                 fi.Success();
  226.             }
  227.             else
  228.             {
  229.                 aClonedScroller = (TScroller*) FreeIfObject( aClonedScroller );
  230.                 fi.ReSignal();
  231.             }
  232.         }
  233.     }
  234.     return aClonedScroller;
  235. } // TScroller::Clone 
  236.  
  237. //----------------------------------------------------------------------------------------
  238. // TScroller::Free: 
  239. //----------------------------------------------------------------------------------------
  240. #pragma segment MAClose
  241.  
  242. TScroller::~TScroller()
  243. {
  244.     fScrollBars[hSel] = (TScrollerScrollBar *)(FreeIfObject(fScrollBars[hSel]));
  245.     fScrollBars[vSel] = (TScrollerScrollBar *)(FreeIfObject(fScrollBars[vSel]));
  246. } // TScroller::Free 
  247.  
  248. //----------------------------------------------------------------------------------------
  249. // TScroller::GetStandardSignature: 
  250. //----------------------------------------------------------------------------------------
  251. #pragma segment MAWriteResource
  252.  
  253. IDType TScroller::GetStandardSignature()    // override 
  254. {
  255.     return kStdScroller;
  256. } // TScroller::GetStandardSignature 
  257.  
  258. //----------------------------------------------------------------------------------------
  259. // TScroller::ReadFields: 
  260. //----------------------------------------------------------------------------------------
  261. #pragma segment MAReadResource
  262.  
  263. void TScroller::ReadFields(TStream* aStream)                // override 
  264. {
  265.     Inherited::ReadFields(aStream);
  266.     
  267.     VPoint scrollLimit;
  268.     VPoint scrollUnits;
  269.     Boolean horzConstraint;
  270.     Boolean vertConstraint;
  271.  
  272.     FailInfo fi;
  273.     Try(fi)
  274.     {
  275.     
  276.         for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  277.             fScrollBarIdentifiers[vhs] = aStream->ReadIDType();
  278.     
  279.         aStream->ReadVPoint(scrollLimit);
  280.         aStream->ReadVPoint(scrollUnits);
  281.         vertConstraint = aStream->ReadBoolean();
  282.         horzConstraint = aStream->ReadBoolean();
  283.         VRect sBarOffsets;
  284.         aStream->ReadVRect(sBarOffsets);
  285.         fSBarOffsets = sBarOffsets;
  286.         fRespondsToFunctionKeys = aStream->ReadBoolean();
  287.         fi.Success();
  288.     }
  289.     else
  290.     {
  291.         this->Free();
  292.         fi.ReSignal();
  293.     }
  294.     
  295.     this->SetScrollLimits(scrollLimit, kDontRedraw);
  296.  
  297.     this->SetScrollParameters(scrollUnits, horzConstraint, vertConstraint);
  298. } // TScroller::ReadFields 
  299.  
  300. //----------------------------------------------------------------------------------------
  301. // TScroller::WriteFields: 
  302. //----------------------------------------------------------------------------------------
  303. #pragma segment MAWriteResource
  304.  
  305. void TScroller::WriteFields(TStream* aStream)        // override 
  306. {
  307.     VHSelect vhs;
  308.  
  309.     Inherited::WriteFields(aStream);
  310.  
  311.     for (vhs = vSel; vhs <= hSel; ++vhs)
  312.         aStream->WriteIDType(fScrollBarIdentifiers[vhs]);
  313.     
  314.     aStream->WriteVPoint(fScrollLimit);                    // write scroll limits
  315.     aStream->WriteVPoint(fScrollUnit);                    // write scroll units
  316.  
  317.     for (vhs = vSel; vhs <= hSel; ++vhs)
  318.         aStream->WriteBoolean(fConstrain[vhs]);
  319.  
  320.     aStream->WriteVRect(fSBarOffsets);                    // write scrollbar offsets
  321.     aStream->WriteBoolean(fRespondsToFunctionKeys);
  322. } // TScroller::WriteFields 
  323.  
  324. //----------------------------------------------------------------------------------------
  325. // TScroller::DoPostCreate: 
  326. //----------------------------------------------------------------------------------------
  327. #pragma segment MAOpen
  328.  
  329. void TScroller::DoPostCreate(TDocument* itsDocument)
  330. {
  331.     Inherited::DoPostCreate(itsDocument);
  332.  
  333.     Boolean needsAdjustScrollBar = FALSE;
  334.  
  335.     if (fSuperView)
  336.     {
  337.         for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  338.             if ((fScrollBarIdentifiers[vhs] != kNoIdentifier) && (fScrollBars[vhs] == NULL))
  339.             {
  340.                 TScrollerScrollBar*    aScrollBar = (TScrollerScrollBar*) fSuperView->FindSubView(fScrollBarIdentifiers[vhs]);
  341.                 if (aScrollBar)
  342.                 {
  343.                     aScrollBar->AttachScroller(this);
  344.                     needsAdjustScrollBar = TRUE;
  345.                 }
  346. #if qDebugMsg
  347.                 else
  348.                 {
  349.                     IDType itsID = fScrollBarIdentifiers[vhs];
  350.                     fprintf(stderr, "###In TScroller::DoPostCreate, can't find scrollbar: %.4s\n", (char *)&itsID);
  351.                 }
  352. #endif
  353.             }
  354.     }
  355.     
  356.     this->AdjustScrollLimits(kDontRedraw);
  357.  
  358.     if (needsAdjustScrollBar)
  359.         this->AdjustScrollBars(kDontInvalidate);
  360. } // TScroller::DoPostCreate 
  361.  
  362. //----------------------------------------------------------------------------------------
  363. // TScroller::AddedASubView: 
  364. //----------------------------------------------------------------------------------------
  365. #pragma segment MAOpen
  366.  
  367. void TScroller::AddedASubView(TView* theSubView)// override 
  368. {
  369.     Inherited::AddedASubView(theSubView);
  370.     
  371.     // if this scroller is the direct superview of the subview
  372.     // accept ownership and recalculate scroll limits
  373.     // (we don't want any other scrollers doing this too)
  374.     if (theSubView->fSuperView == this)
  375.     {
  376.         theSubView->BeInScroller(this);
  377.         this->AdjustScrollLimits(kDontRedraw);
  378.     }
  379. } // TScroller::AddedASubView 
  380.  
  381. //----------------------------------------------------------------------------------------
  382. // TScroller::AdjustScrollBars: 
  383. //----------------------------------------------------------------------------------------
  384. #pragma segment MAScrollerNonRes
  385.  
  386. void TScroller::AdjustScrollLimits(Boolean drawScrollBars)
  387. {
  388.     VRect aggregateExtents(gZeroVRect);
  389.     CSubViewIterator iter(this);
  390.     
  391.     for (TView* aSubView = iter.FirstSubView(); iter.More(); aSubView = iter.NextSubView())
  392.         if (aSubView->fShown)
  393.             aggregateExtents = aggregateExtents | aSubView->GetFrame();        // union the new frame into the aggregate
  394.  
  395.     this->SetScrollLimits(aggregateExtents.GetSize(), drawScrollBars);
  396. }
  397.  
  398. //----------------------------------------------------------------------------------------
  399. // TScroller::AdjustScrollBars: 
  400. //----------------------------------------------------------------------------------------
  401. #pragma segment MAScrollerNonRes
  402.  
  403. void TScroller::AdjustScrollBars(Boolean invalidate)
  404. {
  405.     VHSelect ortho;
  406.  
  407.     for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  408.     {
  409.         TScrollBar * aScrollBar = fScrollBars[vhs];
  410.         if (aScrollBar)
  411.         {
  412.             ortho = gOrthogonal[vhs];
  413.             VPoint loc = fLocation;
  414.             VPoint size = fSize;
  415.  
  416.             loc[vhs] += fSBarOffsets[topLeft][vhs] - 1;
  417.             loc[ortho] += size[ortho];
  418.  
  419.             size[vhs] = size[vhs] - fSBarOffsets[topLeft][vhs] + fSBarOffsets[botRight][vhs] + 2;
  420.             #if 1
  421.                 // ••• Temporary
  422.                 size[ortho] = kSBarSize;
  423.             #else
  424.                 size[ortho] = aScrollBar->fSize[ortho];
  425.             #endif
  426.  
  427.             aScrollBar->SetFrame(VRect(loc, loc + size), invalidate);
  428.         }
  429.     }
  430. } // TScroller::AdjustScrollBars 
  431.  
  432. //----------------------------------------------------------------------------------------
  433. // TScroller::AutoScroll: 
  434. //----------------------------------------------------------------------------------------
  435. #pragma segment MADoCommand
  436.  
  437. void TScroller::AutoScroll(const VPoint& viewPt,
  438.                                   VPoint& delta)
  439. {
  440.     delta = gZeroVPt;
  441.     VRect myExtent(this->GetExtent());
  442.  
  443.     for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  444.         if (viewPt[vhs] < myExtent[topLeft][vhs])
  445.             delta[vhs] = -ProportionalScroll(myExtent[topLeft][vhs] - viewPt[vhs], fScrollUnit[vhs], fTranslation[vhs]);
  446.         else if (viewPt[vhs] > myExtent[botRight][vhs])
  447.             delta[vhs] = ProportionalScroll(viewPt[vhs] - myExtent[botRight][vhs], fScrollUnit[vhs], fMaxTranslation[vhs] - fTranslation[vhs]);
  448. } // TScroller::AutoScroll 
  449.  
  450. //----------------------------------------------------------------------------------------
  451. // TScroller::CreateScrollBar: 
  452. //----------------------------------------------------------------------------------------
  453. #pragma segment MAOpen
  454.  
  455. void TScroller::CreateScrollBar(VHSelect itsDirection)
  456. {
  457.     TScrollerScrollBar * aScrollerScrollBar = new TScrollerScrollBar;
  458.     aScrollerScrollBar->IScrollerScrollBar(fSuperView, gZeroVPt, gZeroVPt, sizeVariable, sizeVariable, itsDirection, fMaxTranslation[itsDirection], this);
  459. } // TScroller::CreateScrollBar 
  460.  
  461. //----------------------------------------------------------------------------------------
  462. // TScroller::DoKeyEvent: 
  463. //----------------------------------------------------------------------------------------
  464. #pragma segment MAScroll
  465. void TScroller::DoKeyEvent(TToolboxEvent* event)// override 
  466. {
  467.     Boolean wasHandled = FALSE;
  468.  
  469.     if (this->IsEnabled() && fRespondsToFunctionKeys)
  470.     {
  471.         wasHandled = TRUE;
  472.         if (event->fText == chPageUp)
  473.         {
  474.             if (fScrollBars[vSel])
  475.                 fScrollBars[vSel]->DeltaValue(VCoordinate(this->ScrollStep(vSel, kControlPageUpPart)));
  476.         }
  477.         else if (event->fText == chPageDown)
  478.         {
  479.             if (fScrollBars[vSel])
  480.                 fScrollBars[vSel]->DeltaValue(VCoordinate(this->ScrollStep(vSel, kControlPageDownPart)));
  481.         }
  482.         else if (event->fText == chHome)
  483.             this->SetLocalOrigin(gZeroVPt, kRedraw);
  484.         else if (event->fText == chEnd)
  485.             this->SetLocalOrigin(VPoint(0, fMaxTranslation.v), kRedraw);
  486.         else
  487.             wasHandled = FALSE;
  488.     }
  489.  
  490.     if (wasHandled)
  491.         this->Update();
  492.     else
  493.         Inherited::DoKeyEvent(event);
  494. } // TScroller::DoKeyEvent 
  495.  
  496. //----------------------------------------------------------------------------------------
  497. // TScroller::DoScroll: 
  498. //----------------------------------------------------------------------------------------
  499. #pragma segment MAScroll
  500.  
  501. void TScroller::DoScroll(const VPoint& delta,
  502.                         Boolean redraw)
  503. {
  504.     VPoint localDelta(delta);
  505.  
  506.     for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  507.     {
  508.         if (localDelta[vhs] < 0)
  509.             localDelta[vhs] = Max(localDelta[vhs], -fTranslation[vhs]);
  510.         else if (localDelta[vhs] > 0)
  511.             localDelta[vhs] = Min(localDelta[vhs], (fMaxTranslation[vhs] - fTranslation[vhs]));
  512.         fTranslation[vhs] += localDelta[vhs];
  513.     }
  514.  
  515.     if (localDelta != gZeroVPt)
  516.     {
  517.         this->InvalidateFocus();
  518.         this->InvalidateCoordinates();
  519.  
  520.         if (redraw)
  521.             this->ScrollDraw(localDelta, kDontInvalidate); // Don't invalidate means "draw don't invalidate"
  522.     }
  523. } // TScroller::DoScroll 
  524.  
  525. //----------------------------------------------------------------------------------------
  526. // TScroller::ForceRedraw: 
  527. //----------------------------------------------------------------------------------------
  528. #pragma segment MAScrollerRes
  529.  
  530. void TScroller::ForceRedraw()        // override 
  531. {
  532.     Inherited::ForceRedraw();
  533.     
  534.     if (fScrollBars[hSel])
  535.         fScrollBars[hSel]->ForceRedraw();
  536.     if (fScrollBars[vSel])
  537.         fScrollBars[vSel]->ForceRedraw();
  538. } // TScroller::ForceRedraw 
  539.  
  540. //----------------------------------------------------------------------------------------
  541. // TScroller::GetScroller: 
  542. //----------------------------------------------------------------------------------------
  543. #pragma segment MAScrollerRes
  544.  
  545. TScroller* TScroller::GetScroller(Boolean)
  546. {
  547.     return this;
  548. } // TScroller::GetScroller 
  549.  
  550. //----------------------------------------------------------------------------------------
  551. // TScroller::HaveScrollBar: 
  552. //----------------------------------------------------------------------------------------
  553. #pragma segment MAScrollerRes
  554.  
  555. void TScroller::HaveScrollBar(TScrollerScrollBar* theScrollBar,
  556.                                      VHSelect direction)
  557. {
  558. #if qDebug
  559.     if ((theScrollBar) && (theScrollBar->fDirection != direction))
  560.         ProgramBreak("Scroll bar is wrong direction.");
  561. #endif
  562.  
  563.     fScrollBars[direction] = theScrollBar;
  564. } // TScroller::HaveScrollBar 
  565.  
  566. //----------------------------------------------------------------------------------------
  567. // TScroller::RemovedASubView: 
  568. //----------------------------------------------------------------------------------------
  569. #pragma segment MAScrollerNonRes
  570.  
  571. void TScroller::RemovedASubView(TView* theSubView)// override 
  572. {
  573.     Inherited::RemovedASubView(theSubView);
  574.     
  575.     if (theSubView->fSuperView == this)
  576.     {
  577.         theSubView->BeInScroller(NULL);
  578.         this->AdjustScrollLimits(kDontRedraw);
  579.     }
  580. } // TScroller::RemovedASubView 
  581.  
  582. //----------------------------------------------------------------------------------------
  583. // TScroller::SetFrame: 
  584. //----------------------------------------------------------------------------------------
  585. #pragma segment MAScrollerNonRes
  586.  
  587. void TScroller::SetFrame(const VRect& newFrame, Boolean invalidate)// override 
  588.  
  589. {
  590.     VPoint oldSize(fSize);
  591.     Inherited::SetFrame(newFrame, invalidate);
  592.     
  593.     this->AdjustScrollBars(invalidate);
  594.  
  595.     if (oldSize != fSize)
  596.         this->SetScrollLimits(fScrollLimit, kDontRedraw);        // Readjust sbar maximums and fMaxTranslation
  597. } // TScroller::SetFrame 
  598.  
  599. //----------------------------------------------------------------------------------------
  600. // TScroller::RevealRect: 
  601. //----------------------------------------------------------------------------------------
  602. #pragma segment MAScroll
  603.  
  604. void TScroller::RevealRect(const VRect& rectToReveal,
  605.                                   const VPoint& minToSee,
  606.                                   Boolean redraw)// override 
  607. {
  608.     VRect myExtent(this->GetExtent());
  609.  
  610.     VPoint delta;
  611.     for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  612.     {
  613.         VCoordinate minAmt = Min(myExtent.GetLength(vhs), minToSee[vhs]);
  614.         VCoordinate coord = rectToReveal[topLeft][vhs] + minAmt - myExtent[botRight][vhs];
  615.         if (coord <= 0)
  616.             coord = Min(0, rectToReveal[botRight][vhs] - minAmt - myExtent[topLeft][vhs]);
  617.         delta[vhs] = coord;
  618.     }
  619.  
  620.     this->ScrollBy(delta, redraw);
  621.     Inherited::RevealRect(rectToReveal, minToSee, redraw);
  622. } // TScroller::RevealRect 
  623.  
  624. //----------------------------------------------------------------------------------------
  625. // TScroller::ScrollBy: 
  626. //----------------------------------------------------------------------------------------
  627. #pragma segment MAScroll
  628.  
  629. void TScroller::ScrollBy(const VPoint& delta,
  630.                                 Boolean redraw)
  631. {
  632.     if (delta != gZeroVPt)
  633.     {
  634.         if (fScrollBars[vSel])
  635.             fScrollBars[vSel]->DeltaValue(delta.v);
  636.             
  637.         if (fScrollBars[hSel])
  638.             fScrollBars[hSel]->DeltaValue(delta.h);
  639.  
  640.         this->DoScroll(delta, redraw);
  641.     }
  642. } // TScroller::ScrollBy 
  643.  
  644. //----------------------------------------------------------------------------------------
  645. // TScroller::ScrollDraw: 
  646. //----------------------------------------------------------------------------------------
  647. #pragma segment MAScroll
  648.  
  649. void TScroller::ScrollDraw(const VPoint& delta,
  650.                                   Boolean invalidate)
  651. {
  652.     if (!this->GetVisibleExtent().Empty() && this->IsShown() && this->Focus())
  653.     {
  654.         CRect visRect((*GetClipRegion(qd.thePort))->rgnBBox); // just test the clip, it's faster
  655.  
  656. #if qDebug
  657.         if (gIntenseDebugging)
  658.             WriteFocus();
  659. #endif
  660.         if (!visRect.Empty())
  661.         {
  662.             const VRect visVRect(visRect);
  663.             if (((visVRect - delta) & visVRect).Empty()) // too far to scrollrect 
  664.                 this->InvalidateRect(visRect);
  665.             else
  666.             {
  667.                 CTemporaryRegion tempRgn;
  668.  
  669.                 ScrollRect(visRect, (short)(-delta.h), (short)(-delta.v), tempRgn);
  670.                 this->InvalidateRegion(tempRgn);
  671.             }
  672.         
  673.             if (!invalidate)
  674.                 this->Update();
  675.         }
  676.     }
  677. } // TScroller::ScrollDraw 
  678.  
  679. //----------------------------------------------------------------------------------------
  680. // TScroller::ScrollRelative: 
  681. //----------------------------------------------------------------------------------------
  682. #pragma segment MAScroll
  683.  
  684. VCoordinate TScroller::ScrollRelative(VHSelect vhs,
  685.                                              VCoordinate sBarValue)
  686. {
  687.     VPoint pixelDelta(0, 0);
  688.     VCoordinate newValue;
  689.  
  690.     if ((fConstrain[vhs] && (sBarValue != fMaxTranslation[vhs])))
  691.         newValue = (sBarValue + fScrollUnit[vhs] / 2) / fScrollUnit[vhs] * fScrollUnit[vhs];
  692.     else
  693.         newValue = sBarValue;
  694.  
  695.     pixelDelta[vhs] = newValue - fTranslation[vhs];
  696.     this->DoScroll(pixelDelta, kRedraw);
  697.     return (newValue - sBarValue);
  698. } // TScroller::ScrollRelative 
  699.  
  700. //----------------------------------------------------------------------------------------
  701. // TScroller::ScrollStep: 
  702. //----------------------------------------------------------------------------------------
  703. #pragma segment MAScroll
  704.  
  705. VCoordinate TScroller::ScrollStep(VHSelect vhs,
  706.                                          short partCode)
  707. {
  708.     VCoordinate scrollUnit = fScrollUnit[vhs];
  709.     VCoordinate delta;
  710.  
  711.     switch (partCode)
  712.     {
  713.         case kControlUpButtonPart:
  714.         case kControlDownButtonPart:
  715.             delta = scrollUnit;
  716.             break;
  717.             
  718.         case kControlPageUpPart:
  719.         case kControlPageDownPart:
  720.             delta = fSize[vhs] - scrollUnit;
  721.             break;
  722.             
  723. #if qDebug
  724.         default:
  725.             {
  726.                 CStr255 theString;
  727.                 ConcatNumber("TScroller::ScrollStep: bad part code =", partCode, theString);
  728.                 ProgramBreak(theString);
  729.             }
  730.             break;
  731. #endif
  732.  
  733.     }
  734.  
  735.     if ((partCode == kControlUpButtonPart) || (partCode == kControlPageUpPart))
  736.         delta = -delta;
  737.  
  738.     // Constrain if necessary 
  739.     if (fConstrain[vhs] && (scrollUnit != 0))
  740.     {
  741.         VCoordinate adjustment = (Max(0, fTranslation[vhs] + delta)) % scrollUnit;
  742.         if (adjustment != 0)
  743.             if (delta > 0)
  744.                 delta -= adjustment;
  745.             else
  746.                 delta += (scrollUnit - adjustment);
  747.     }
  748.  
  749.     VPoint deltaPt(0, 0);
  750.     deltaPt[vhs] = delta;
  751.  
  752.     this->DoScroll(deltaPt, kRedraw);
  753.     return delta;
  754. } // TScroller::ScrollStep 
  755.  
  756. //----------------------------------------------------------------------------------------
  757. // TScroller::SetLocalOrigin: 
  758. //----------------------------------------------------------------------------------------
  759. #pragma segment MAScroll
  760.  
  761. void TScroller::SetLocalOrigin(const VPoint& newOrigin,
  762.                                       Boolean redraw)
  763. {
  764.     ScrollBy(newOrigin - fTranslation, redraw);
  765. } // TScroller::SetLocalOrigin 
  766.  
  767. //----------------------------------------------------------------------------------------
  768. // TScroller::SetScrollLimits: 
  769. //----------------------------------------------------------------------------------------
  770. #pragma segment MAScrollerNonRes
  771.  
  772. void TScroller::SetScrollLimits(const VPoint& scrollLimit,
  773.                                        Boolean drawScrollBars)
  774. {
  775.     VPoint newTranslation(fTranslation);
  776.  
  777.     fScrollLimit = scrollLimit;
  778.     for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  779.     {
  780.         VCoordinate maxCoord = Max(0, scrollLimit[vhs] - fSize[vhs]);
  781.         
  782.         fMaxTranslation[vhs] = maxCoord;
  783.         if (fScrollBars[vhs])
  784.             fScrollBars[vhs]->SetLongMax(maxCoord, drawScrollBars);
  785.  
  786.         if (maxCoord < fTranslation[vhs])
  787.             newTranslation[vhs] = maxCoord;
  788.     }
  789.  
  790.     // This is very similar to ScrollBy except that the scrollbars
  791.     // have to react in the opposite direction as the scrolling.
  792.     VPoint        delta = newTranslation - fTranslation;
  793.     if (delta != gZeroVPt)
  794.     {
  795.         if (fScrollBars[vSel])
  796.             fScrollBars[vSel]->DeltaValue(-delta.v);
  797.             
  798.         if (fScrollBars[hSel])
  799.             fScrollBars[hSel]->DeltaValue(-delta.h);
  800.     
  801.         this->DoScroll(delta, kRedraw);
  802.     }
  803. } // TScroller::SetScrollLimits 
  804.  
  805. //----------------------------------------------------------------------------------------
  806. // TScroller::SetScrollParameters: 
  807. //----------------------------------------------------------------------------------------
  808. #pragma segment MAScrollerNonRes
  809.  
  810. void TScroller::SetScrollParameters(const VPoint& units,
  811.                                            Boolean horzConstraint,
  812.                                            Boolean vertConstraint)
  813. {
  814.     fScrollUnit = units;
  815.     fConstrain[hSel] = horzConstraint;
  816.     fConstrain[vSel] = vertConstraint;
  817. } // TScroller::SetScrollParameters 
  818.  
  819. //----------------------------------------------------------------------------------------
  820. // TScroller::SubViewChangedFrame: 
  821. //----------------------------------------------------------------------------------------
  822. #pragma segment MAScrollerNonRes
  823.  
  824. void TScroller::SubViewChangedFrame(TView* ,
  825.                                           const VRect&,
  826.                                           const VRect&,
  827.                                                 Boolean invalidate)// override 
  828. {
  829.     this->AdjustScrollLimits(invalidate);
  830. } // TScroller::SubViewChangedFrame 
  831.  
  832. #if qDrag
  833.  
  834. //----------------------------------------------------------------------------------------
  835. // TScroller::GetDragScrollDelta: 
  836. //----------------------------------------------------------------------------------------
  837. #pragma segment MADragNonRes
  838.  
  839. VPoint TScroller::GetDragScrollDelta(const VPoint& mouseInWindow)
  840. {
  841.     static const short kDragScrollRange = 16;            
  842.     
  843.     VPoint        scrollDelta(gZeroPt);
  844.             
  845.     TView* aScroller = this;
  846.     VRect scrollerExtent(aScroller->GetVisibleExtent());
  847.     while(aScroller)        // convert to window coords
  848.     {
  849.         if (aScroller->fSuperView)
  850.             aScroller->LocalToSuperVRect(scrollerExtent);
  851.         aScroller = aScroller->fSuperView;
  852.     }
  853.     
  854.     VHSelect    vhSelect;
  855.     for (vhSelect = vSel; vhSelect <= hSel; vhSelect++)
  856.     {
  857.         if (fScrollBars[vhSelect])
  858.         {
  859.             TView* aScrollBar = fScrollBars[vhSelect];
  860.             VRect scrollBarExtent(aScrollBar->GetVisibleExtent());
  861.             while(aScrollBar)    // convert to window coords
  862.             {
  863.                 if(aScrollBar->fSuperView)
  864.                     aScrollBar->LocalToSuperVRect(scrollBarExtent);
  865.                 aScrollBar = aScrollBar->fSuperView;
  866.             }
  867.             
  868.             VCoordinate    firstDiff = scrollerExtent[topLeft][vhSelect] - scrollBarExtent[botRight][vhSelect];
  869.             VCoordinate    secondDiff = scrollBarExtent[topLeft][vhSelect] - scrollerExtent[botRight][vhSelect];
  870.             
  871.             // if scroll bar is adjacent to the scroller, union it into the scroller extent
  872.             if (firstDiff <= 1 || secondDiff <= 1)
  873.                 scrollerExtent = (scrollerExtent | scrollBarExtent);
  874.         }
  875.     }
  876.                     
  877.     if (scrollerExtent.Contains(mouseInWindow))
  878.     {
  879.         VPoint     extentDelta(kDragScrollRange, kDragScrollRange);
  880.         
  881.         scrollerExtent.Inset(extentDelta);        // inset the extent
  882.         
  883.         if (!scrollerExtent.Contains(mouseInWindow))
  884.         {
  885.             for (vhSelect = vSel; vhSelect <= hSel; vhSelect++)
  886.             {
  887.                 // adjust scroll delta. test scrolling in all 4 directions
  888.                 // if the scroller scrolls up AND down, it'll resolve to a
  889.                 // no vertical scroll. this handles overlapping opposing scroll areas
  890.                 if ((mouseInWindow[vhSelect] < scrollerExtent[topLeft][vhSelect]) && 
  891.                     (fTranslation[vhSelect] > 0))
  892.                         scrollDelta[vhSelect] = -fScrollUnit[vhSelect];
  893.                 
  894.                 if ((mouseInWindow[vhSelect] > scrollerExtent[botRight][vhSelect]) &&
  895.                     (fMaxTranslation[vhSelect] - fTranslation[vhSelect]) > 0)
  896.                         scrollDelta[vhSelect] = fScrollUnit[vhSelect];
  897.             }
  898.         }
  899.     }
  900.     return scrollDelta;
  901. }
  902.     
  903. #endif
  904.  
  905. //----------------------------------------------------------------------------------------
  906. // End of UScroller.cp 
  907.  
  908. #pragma segment Inline
  909.